<template>
  <div class="emotional-timeline">
    <!-- 对话显示区域 -->
    <div class="conversation-timeline">
      <div v-for="(turn, index) in props.dialogueTurns" 
           :key="index" 
           class="dialogue-bubble-container"
           :class="{ 'right-aligned': isRightAligned(turn) }">
        <div class="speaker-label">{{ getSpeakerLabel(turn.speaker) }}</div>
        <div class="dialogue-bubble" 
             :class="[turn.emotion.type, isRightAligned(turn) ? 'bubble-right' : 'bubble-left']">
          <div class="bubble-content">{{ turn.text }}</div>
          <div class="bubble-metadata">
            <span class="turn-number">回合: {{ turn.turn }}</span>
            <div class="emotion-tag" :class="turn.emotion.type">
              <span class="emotion-icon">{{ getEmotionIcon(turn.emotion.type) }}</span>
              <span class="emotion-label">{{ getEmotionLabel(turn.emotion.type) }}</span>
              <span class="emotion-intensity">强度: {{ turn.emotion.intensity }}</span>
            </div>
          </div>
          <div v-if="turn.subText" class="bubble-subtext">
            暗示: {{ turn.subText }}
          </div>
        </div>
      </div>
    </div>
    
    <!-- 图表可视化区域 -->
    <div class="visualization-container">
      <h4 class="visualization-title">情感强度图表</h4>
      <div class="timeline-visualization" ref="timelineContainer" style="position: relative;">
        <!-- 这里将渲染D3.js图表 -->
        
        <!-- 悬浮提示框 - 绝对定位在容器内 -->
        <div class="timeline-tooltip" v-if="showTooltip" :style="tooltipStyle">
          <div class="tooltip-header">
            <span class="tooltip-speaker">{{ selectedTurn?.speaker }}</span>
            <span class="tooltip-turn">第 {{ selectedTurn?.turn }} 轮</span>
          </div>
          <div class="tooltip-content">
            <p class="tooltip-text">{{ selectedTurn?.text }}</p>
            <p class="tooltip-subtext" v-if="selectedTurn?.subText">暗示: {{ selectedTurn?.subText }}</p>
          </div>
          <div class="tooltip-emotion" :class="selectedTurn?.emotion.type">
            情绪: <span class="emotion-icon">{{ getEmotionIcon(selectedTurn?.emotion.type) }}</span> 
            <span class="emotion-type">{{ getEmotionLabel(selectedTurn?.emotion.type) }}</span>
            <span class="tooltip-intensity">(强度: {{ selectedTurn?.emotion.intensity }})</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, computed } from 'vue';
import * as d3 from 'd3';
import type { PropType } from 'vue';
import type { DialogueTurn, CriticalJunction } from '../../types/analysis';

const props = defineProps({
  dialogueTurns: {
    type: Array as PropType<DialogueTurn[]>,
    required: true
  },
  criticalJunctions: {
    type: Array as PropType<CriticalJunction[]>,
    default: () => []
  }
});

const timelineContainer = ref<HTMLElement | null>(null);
const viewMode = ref<'absolute' | 'relative'>('absolute');
const showTooltip = ref(false);
const selectedTurn = ref<DialogueTurn | null>(null);
const selectedPointPosition = ref({ x: 0, y: 0 });
const firstSpeaker = computed(() => {
  if (props.dialogueTurns && props.dialogueTurns.length > 0) {
    return props.dialogueTurns[0].speaker;
  }
  return '';
});

const tooltipStyle = computed(() => {
  if (!selectedPointPosition.value || !showTooltip.value) {
    return { display: 'none' as const };
  }
  
  const x = selectedPointPosition.value.x;
  const y = selectedPointPosition.value.y;
  
  const containerWidth = timelineContainer.value?.clientWidth || 800;
  
  if (x < containerWidth / 2) {
    return {
      position: 'absolute' as const,
      left: `${x + 20}px`, 
      top: `${y - 20}px`,  
      transform: 'none' as const
    };
  } else {
    return {
      position: 'absolute' as const,
      right: `${containerWidth - x + 20}px`, 
      top: `${y - 20}px`, 
      transform: 'none' as const
    };
  }
});

// 判断气泡是否显示在右侧（第一个角色）
const isRightAligned = (turn: DialogueTurn): boolean => {
  return turn.speaker === firstSpeaker.value;
};

// 获取显示名称
const getSpeakerLabel = (speaker: string): string => {
  const speakerMap: Record<string, string> = {
    'A': 'A',
    'B': 'B',
    'man': '男性',
    'woman': '女性',
    'user': '用户',
    'assistant': '助手'
  };
  
  return speakerMap[speaker] || speaker;
};

// 获取情绪标签
const getEmotionLabel = (type?: string): string => {
  const emotionLabels: Record<string, string> = {
    'positive': '积极',
    'negative': '消极',
    'neutral': '中性',
    'surprise': '惊讶',
    'fear': '恐惧',
    'sadness': '悲伤',
    'joy': '喜悦',
    'anger': '愤怒',
    'disgust': '厌恶'
  };
  
  return type ? emotionLabels[type] || type : '未知';
};

const initializeTimeline = () => {
  if (!timelineContainer.value) return;

  const container = d3.select(timelineContainer.value);
  const width = timelineContainer.value.clientWidth;
  const height = 300; // 固定高度以确保图表有足够空间
  const margin = { top: 30, right: 40, bottom: 40, left: 50 };

  container.selectAll('svg').remove();

  const svg = container.append('svg')
    .attr('width', width)
    .attr('height', height)
    .attr('viewBox', [0, 0, width, height]);

  const xScale = d3.scaleLinear()
    .domain([0, props.dialogueTurns.length - 1])
    .range([margin.left, width - margin.right]);

  const yScale = d3.scaleLinear()
    .domain([
      d3.min(props.dialogueTurns, d => viewMode.value === 'absolute' ? d.emotion.intensity : d.emotion.relativeIntensity) || -1,
      d3.max(props.dialogueTurns, d => viewMode.value === 'absolute' ? d.emotion.intensity : d.emotion.relativeIntensity) || 1
    ])
    .range([height - margin.bottom, margin.top]);

  const xAxis = d3.axisBottom(xScale)
    .ticks(Math.min(props.dialogueTurns.length, 10))
    .tickFormat((d: any) => `${Math.floor(d) + 1}`);

  const yAxis = d3.axisLeft(yScale)
    .ticks(5)
    .tickFormat((d: any) => d.toFixed(1));

  svg.append('g')
    .attr('class', 'x-axis')
    .attr('transform', `translate(0, ${height - margin.bottom})`)
    .call(xAxis);

  svg.append('g')
    .attr('class', 'y-axis')
    .attr('transform', `translate(${margin.left}, 0)`)
    .call(yAxis);

  svg.append('text')
    .attr('class', 'axis-label')
    .attr('x', width / 2)
    .attr('y', height - margin.bottom + 30)
    .attr('text-anchor', 'middle')
    .text('对话轮次');

  svg.append('text')
    .attr('class', 'axis-label')
    .attr('transform', 'rotate(-90)')
    .attr('x', -height / 2)
    .attr('y', margin.left - 35)
    .attr('text-anchor', 'middle')
    .text('情感强度');

  // 添加网格线增强可读性
  svg.append('g')
    .attr('class', 'grid-lines')
    .selectAll('line')
    .data(yScale.ticks(5))
    .enter()
    .append('line')
    .attr('x1', margin.left)
    .attr('x2', width - margin.right)
    .attr('y1', d => yScale(d))
    .attr('y2', d => yScale(d))
    .attr('stroke', '#e0e0e0')
    .attr('stroke-dasharray', '3,3');

  // 添加零线，使其更加突出
  if (yScale.domain()[0] < 0 && yScale.domain()[1] > 0) {
    svg.append('line')
      .attr('class', 'zero-line')
      .attr('x1', margin.left)
      .attr('x2', width - margin.right)
      .attr('y1', yScale(0))
      .attr('y2', yScale(0))
      .attr('stroke', '#9e9e9e')
      .attr('stroke-width', 1.5);
  }

  // 用不同颜色区分正面情绪和负面情绪的区域
  const areaPositive = d3.area<DialogueTurn>()
    .x((_, i) => xScale(i))
    .y0(yScale(0))
    .y1(d => {
      const value = viewMode.value === 'absolute' ? d.emotion.intensity : d.emotion.relativeIntensity;
      return value > 0 ? yScale(value) : yScale(0);
    })
    .curve(d3.curveMonotoneX);

  const areaNegative = d3.area<DialogueTurn>()
    .x((_, i) => xScale(i))
    .y0(yScale(0))
    .y1(d => {
      const value = viewMode.value === 'absolute' ? d.emotion.intensity : d.emotion.relativeIntensity;
      return value < 0 ? yScale(value) : yScale(0);
    })
    .curve(d3.curveMonotoneX);

  svg.append('path')
    .datum(props.dialogueTurns)
    .attr('class', 'area-positive')
    .attr('fill', 'rgba(76, 175, 80, 0.2)')
    .attr('d', areaPositive);

  svg.append('path')
    .datum(props.dialogueTurns)
    .attr('class', 'area-negative')
    .attr('fill', 'rgba(244, 67, 54, 0.2)')
    .attr('d', areaNegative);

  const line = d3.line<DialogueTurn>()
    .x((_, i) => xScale(i))
    .y(d => yScale(viewMode.value === 'absolute' ? d.emotion.intensity : d.emotion.relativeIntensity))
    .curve(d3.curveMonotoneX);

  svg.append('path')
    .datum(props.dialogueTurns)
    .attr('class', 'emotion-line')
    .attr('fill', 'none')
    .attr('stroke', '#2196F3')
    .attr('stroke-width', 2)
    .attr('d', line);

  const points = svg.append('g')
    .selectAll('circle')
    .data(props.dialogueTurns)
    .join('circle')
    .attr('class', 'timeline-point')
    .attr('cx', (_, i) => xScale(i))
    .attr('cy', d => yScale(viewMode.value === 'absolute' ? d.emotion.intensity : d.emotion.relativeIntensity))
    .attr('r', 6)
    .attr('fill', d => getEmotionColor(d.emotion.type))
    .attr('stroke', '#fff')
    .attr('stroke-width', 2);

  points.on('mouseover', (_, d: DialogueTurn) => {
    const i = props.dialogueTurns.findIndex(turn => turn.turn === d.turn);
    const x = xScale(i);
    const y = yScale(viewMode.value === 'absolute' ? d.emotion.intensity : d.emotion.relativeIntensity);
    
    selectedTurn.value = d;
    selectedPointPosition.value = { 
      x: x, 
      y: y 
    };
    showTooltip.value = true;
  }).on('mouseout', () => {
    showTooltip.value = false;
  });

  // 标记关键转折点
  if (props.criticalJunctions && props.criticalJunctions.length > 0) {
    svg.append('g')
      .selectAll('rect')
      .data(props.criticalJunctions)
      .join('rect')
      .attr('class', 'critical-junction')
      .attr('x', d => {
        const turnIndex = props.dialogueTurns.findIndex(turn => turn.turn === d.turn);
        return xScale(turnIndex) - 8;
      })
      .attr('y', d => {
        const turn = props.dialogueTurns.find(t => t.turn === d.turn);
        if (!turn) return 0;
        return yScale(viewMode.value === 'absolute' ? turn.emotion.intensity : turn.emotion.relativeIntensity) - 8;
      })
      .attr('width', 16)
      .attr('height', 16)
      .attr('fill', 'none')
      .attr('stroke', '#FFC107')
      .attr('stroke-width', 2)
      .attr('rx', 2)
      .attr('ry', 2)
      .attr('transform', 'rotate(45)');
  }
};

const getEmotionColor = (type: string): string => {
  const colorMap: Record<string, string> = {
    'positive': '#4CAF50',  // 绿色
    'negative': '#F44336',  // 红色
    'neutral': '#9E9E9E',   // 灰色
    'surprise': '#FF9800',  // 橙色
    'fear': '#9C27B0',      // 紫色
    'sadness': '#2196F3',   // 蓝色
    'joy': '#FFC107',       // 黄色
    'anger': '#E91E63',     // 粉色
    'disgust': '#795548'    // 棕色
  };
  
  return colorMap[type] || '#9E9E9E';
};

const getEmotionIcon = (type?: string): string => {
  const emotionIcons: Record<string, string> = {
    'positive': '😊',
    'negative': '😠',
    'neutral': '😐',
    'surprise': '😲',
    'fear': '😨',
    'sadness': '😢',
    'joy': '😄',
    'anger': '😡',
    'disgust': '🤢'
  };
  
  return type ? emotionIcons[type] || '❓' : '❓';
};

onMounted(() => {
  initializeTimeline();
  window.addEventListener('resize', initializeTimeline);
});

watch(() => props.dialogueTurns, () => {
  initializeTimeline();
}, { deep: true });

onUnmounted(() => {
  window.removeEventListener('resize', initializeTimeline);
});
</script>

<style scoped>
.emotional-timeline {
  display: flex;
  flex-direction: column;
  gap: 2rem;
  width: 100%;
}

/* 对话气泡样式 */
.conversation-timeline {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1rem;
  background-color: #f9f9f9;
  border-radius: 8px;
  max-height: 400px;
  overflow-y: auto;
}

.dialogue-bubble-container {
  display: flex;
  flex-direction: column;
  width: 100%;
  position: relative;
}

.speaker-label {
  font-size: 0.75rem;
  color: #666;
  margin-bottom: 0.25rem;
}

.dialogue-bubble-container.right-aligned {
  align-items: flex-end;
}

.dialogue-bubble-container.right-aligned .speaker-label {
  align-self: flex-end;
}

.dialogue-bubble {
  max-width: 80%;
  border-radius: 12px;
  padding: 0.75rem;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
  position: relative;
}

.bubble-left {
  background-color: #e3f2fd;
  border-top-left-radius: 2px;
  align-self: flex-start;
}

.bubble-right {
  background-color: #f3e5f5;
  border-top-right-radius: 2px;
  align-self: flex-end;
}

.bubble-content {
  font-size: 0.875rem;
  line-height: 1.4;
  word-break: break-word;
}

.bubble-metadata {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 0.5rem;
  font-size: 0.75rem;
  color: #666;
  border-top: 1px dashed #ddd;
  padding-top: 0.5rem;
}

.turn-number {
  color: #888;
}

.emotion-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.125rem 0.375rem;
  border-radius: 1rem;
  background-color: rgba(0, 0, 0, 0.05);
  font-size: 0.75rem;
}

.emotion-icon {
  font-size: 1rem;
}

.emotion-label {
  font-weight: 600;
}

.emotion-intensity {
  font-size: 0.675rem;
  opacity: 0.8;
}

.bubble-subtext {
  font-size: 0.75rem;
  font-style: italic;
  color: #666;
  margin-top: 0.5rem;
}

/* 图表区域样式 */
.visualization-container {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid #eee;
}

.visualization-title {
  font-size: 1rem;
  font-weight: 600;
  color: #333;
  margin-bottom: 1rem;
  padding-left: 0.5rem;
  border-left: 3px solid #7c3aed;
}

.timeline-visualization {
  height: 300px;
  width: 100%;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  padding: 1rem;
  background-color: white;
}

.timeline-tooltip {
  position: absolute;
  background-color: white;
  border: 1px solid #e0e0e0;
  border-radius: 6px;
  padding: 8px 12px;
  pointer-events: none;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  width: max-content;
  max-width: 300px;
  font-size: 0.75rem;
  z-index: 10;
}

.tooltip-header {
  display: flex;
  justify-content: space-between;
  border-bottom: 1px solid #f0f0f0;
  padding-bottom: 4px;
  margin-bottom: 4px;
}

.tooltip-speaker {
  font-weight: bold;
}

.tooltip-turn {
  color: #666;
}

.tooltip-content {
  margin-bottom: 6px;
}

.tooltip-text {
  margin: 0 0 4px 0;
}

.tooltip-subtext {
  margin: 0;
  font-style: italic;
  color: #666;
  font-size: 0.7rem;
}

.tooltip-intensity {
  font-size: 0.7rem;
  color: #666;
}

.axis-label {
  font-size: 0.75rem;
  fill: #666;
}

.x-axis, .y-axis {
  font-size: 0.75rem;
  color: #666;
}

.x-axis line, .y-axis line {
  stroke: #ddd;
}

.emotion-line {
  stroke-linecap: round;
  stroke-linejoin: round;
}

.timeline-point {
  cursor: pointer;
  transition: r 0.2s;
}

.timeline-point:hover {
  r: 8;
}

.critical-junction {
  cursor: pointer;
}

/* 情绪类型颜色 */
.positive {
  color: #4caf50;
}

.negative {
  color: #f44336;
}

.neutral {
  color: #9e9e9e;
}

.surprise {
  color: #ff9800;
}

.fear {
  color: #9c27b0;
}

.sadness {
  color: #2196f3;
}

.joy {
  color: #ffc107;
}

.anger {
  color: #e91e63;
}

.disgust {
  color: #795548;
}

/* 自定义滚动条 */
.conversation-timeline::-webkit-scrollbar {
  width: 6px;
}

.conversation-timeline::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.conversation-timeline::-webkit-scrollbar-thumb {
  background: #c4c4c4;
  border-radius: 3px;
}

.conversation-timeline::-webkit-scrollbar-thumb:hover {
  background: #a0a0a0;
}

/* 媒体查询适配移动设备 */
@media (max-width: 768px) {
  .emotional-timeline {
    gap: 1rem;
  }
  
  .conversation-timeline {
    max-height: 300px;
  }
  
  .dialogue-bubble {
    max-width: 85%;
  }
  
  .bubble-content {
    font-size: 0.8rem;
  }
}

/* 深色模式 */
@media (prefers-color-scheme: dark) {
  .conversation-timeline {
    background-color: #262626;
  }
  
  .bubble-left {
    background-color: #263238;
  }
  
  .bubble-right {
    background-color: #311b92;
  }
  
  .bubble-content, .speaker-label {
    color: #e0e0e0;
  }
  
  .bubble-metadata, .bubble-subtext {
    color: #aaa;
    border-top-color: #444;
  }
  
  .emotion-tag {
    background-color: rgba(255, 255, 255, 0.1);
  }
  
  .timeline-visualization {
    background-color: #262626;
    border-color: #444;
  }
  
  .visualization-title {
    color: #e0e0e0;
  }
  
  .timeline-tooltip {
    background-color: #1e1e1e;
    border-color: #444;
    color: #e0e0e0;
  }
  
  .tooltip-header {
    border-bottom-color: #444;
  }
  
  .axis-label, .x-axis, .y-axis {
    fill: #aaa;
    color: #aaa;
  }
  
  .x-axis line, .y-axis line, .grid-lines line {
    stroke: #444;
  }
  
  .visualization-container {
    border-top-color: #444;
  }
}
</style>
